import sqlite3
import queue
import threading
from utils import log_info, log_exception, log_warning, log_debug
from typing import Optional
from configs import DB_PATH


class DatabasePool:
    """SQLite数据库连接池"""
    _lock = threading.Lock()

    def __init__(self, max_connections: int = 10):
        """
        初始化数据库连接池
        :param db_path: 数据库文件路径
        :param max_connections: 最大连接数，默认为10
        """
        self.db_path = DB_PATH
        self.max_connections = max_connections
        self.connections = queue.Queue(maxsize=max_connections)
        # 预先创建少量连接
        for _ in range(min(3, max_connections)):
            self._create_connection()

    def _create_connection(self) -> sqlite3.Connection:
        """创建新的数据库连接"""
        try:
            conn = sqlite3.connect(self.db_path)
            self.connections.put(conn)
            log_debug(f"创建数据库连接成功，当前连接池大小: {self.connections.qsize()}/{self.max_connections}")
            return conn
        except sqlite3.Error as e:
            log_exception(f"创建数据库连接失败: {str(e)}")
            return None

    def get_connection(self) -> Optional[sqlite3.Connection]:
        """
        从连接池获取一个连接
        :return: 数据库连接对象，如果获取失败返回None
        """
        try:
            # 等待0.5秒，如果没有可用连接则尝试创建新连接
            return self.connections.get(timeout=0.2)
        except queue.Empty:
            # 如果没有可用连接，且未达到最大连接数，则创建新连接
            if self.connections.qsize() < self.max_connections:
                return self._create_connection()
            log_warning(f"数据库连接池已满，无法获取连接，当前连接数: {self.connections.qsize()}/{self.max_connections}")
            return None

    def release_connection(self, conn: sqlite3.Connection) -> None:
        """
        释放连接回连接池
        :param conn: 要释放的数据库连接
        """
        if conn:
            try:
                # 直接放回连接池，不再验证连接有效性
                # 对于SQLite，连接通常不会失效，除非数据库文件被删除或损坏
                self.connections.put(conn, block=False)
                log_debug(f"释放数据库连接成功，当前连接池大小: {self.connections.qsize()}/{self.max_connections}")
            except queue.Full:
                log_warning(f"连接池已满，关闭多余连接")
                conn.close()
            except Exception as e:
                log_exception(f"释放连接失败: {str(e)}")
                try:
                    conn.close()
                except:
                    pass

    def close_all_connections(self) -> None:
        """关闭连接池中的所有连接"""
        while not self.connections.empty():
            try:
                conn = self.connections.get(block=False)
                conn.close()
                log_debug("关闭数据库连接成功")
            except sqlite3.Error as e:
                log_exception(f"关闭数据库连接失败: {str(e)}")


# 全局连接池实例
def get_db_pool() -> DatabasePool:
    """
    获取数据库连接池实例
    :param db_path: 数据库文件路径
    :return: 数据库连接池实例
    """
    return DatabasePool()